package com.taptech.doufu.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.ref.SoftReference;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.widget.ImageView;

import com.taptech.doufu.constant.Constant;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

public class AsyncImageLoader {

	private HashMap<String, SoftReference<Drawable>> imageCache;
	private HashMap<String ,MyAsyncTask> map=new HashMap<String, MyAsyncTask>();
	private Map<ImageView, String> imageViews = Collections  
	            .synchronizedMap(new WeakHashMap<ImageView, String>());  
//	    // 线程池  
//	    ExecutorService executorService; 
	public enum ImageShape 
	{
		Normal, Round, Corner
	}
	
	public enum ImageType {
		Avatar, Banner
	}

	
	public AsyncImageLoader() {
		imageCache = new HashMap<String, SoftReference<Drawable>>();
//		if(executorService==null)
//		 executorService = Executors.newFixedThreadPool(5);  
	}
	
	/**
	 * load normal drawable, if want key to set some things
	 * @return 
	 * 
	 * */
	public void   loadDrawable(final String imageUrl,final ImageView mImageView,
			final ImageCallback imageCallback, final boolean compress,final int width,final int height) {
             imageViews.put(mImageView, imageUrl);  
			SoftReference<Drawable> softReference = imageCache.get(imageUrl);
			Drawable drawable=null;
			if(softReference!=null){
				drawable=softReference.get();
			}
			//先从软引用中拿数据
			if(drawable != null && mImageView != null && imageUrl.equals(mImageView.getTag())){
				imageCallback.imageLoaded(drawable,imageUrl);
			}
//			else{
//				queuePhoto(imageUrl,  mImageView, imageCallback, compress, width, height);
//			}
			else if(imageUrl != null && needCreateNewTask(mImageView)){
			MyAsyncTask task = new MyAsyncTask(imageUrl, mImageView,imageCallback,compress,width,height);
			if(mImageView != null){
				task.execute();
				//将对应的url对应的任务存起来
				map.put(imageUrl, task);
				}
		}
			
			
		/*
	 	if (drawable != null) {
 			return drawable;
 		}	
		  	final Handler handler = new Handler() {
			@Override
			public void handleMessage(Message message) {
				imageCallback.imageLoaded((Drawable) message.obj, imageUrl);
			}
		};
		  new Thread() {
			@Override
			public void run() {
				Drawable drawable = null;
				
				Bitmap normalBitmap = loadImageFromUrl(imageUrl, compress);
				
				if (normalBitmap != null) {
					drawable = new BitmapDrawable(normalBitmap);
				}
				
				System.gc();
				
				imageCache.put(imageUrl, new SoftReference<Drawable>(drawable));
				Message message = handler.obtainMessage(0, drawable);
				handler.sendMessage(message);
				
			}
		}.start();*/
//		return null;
	}
	
	/**
	 * load circle drawable
	 * 
	 * */
	public Drawable loadCircleDrawable(final String imageUrl,
			final ImageCallback imageCallback,final int width,final int height) {
		if (imageCache.containsKey(imageUrl)) {
			SoftReference<Drawable> softReference = imageCache.get(imageUrl);
			Drawable drawable = softReference.get();
			if (drawable != null) {
				return drawable;
			}
		}
		final Handler handler = new Handler() {
			@Override
			public void handleMessage(Message message) {
				imageCallback.imageLoaded((Drawable) message.obj, imageUrl);
			}
		};
		new Thread() {
			@Override
			public void run() {
				Drawable drawable = null;
				
				Bitmap circleBitmap = BitmapUtil.getCircleBitmap(loadImageFromUrl(imageUrl, true,width,height));
				
				if (circleBitmap != null) {
					drawable = new BitmapDrawable(circleBitmap);
				}
				
				imageCache.put(imageUrl, new SoftReference<Drawable>(drawable));
				System.gc();
				Message message = handler.obtainMessage(0, drawable);
				handler.sendMessage(message);
				
			}
		}.start();
		return null;
	}
	
	/**
	 * load circle with ring drawable
	 * 
	 * */
	public Drawable loadCircleWithRingDrawable(final String imageUrl,
			final ImageCallback imageCallback, final int ringWidth,final int  width,final int height) {
		if (imageCache.containsKey(imageUrl)) {
			SoftReference<Drawable> softReference = imageCache.get(imageUrl);
			Drawable drawable = softReference.get();
			if (drawable != null) {
				return drawable;
			}
		}
		final Handler handler = new Handler() {
			@Override
			public void handleMessage(Message message) {
				imageCallback.imageLoaded((Drawable) message.obj, imageUrl);
			}
		};
		new Thread() {
			@Override
			public void run() {
				Drawable drawable = null;
				
				Bitmap circleWithRingBitmap = BitmapUtil.getCircleBitmapWithRing(loadImageFromUrl(imageUrl, true,width,height), ringWidth);
				
				if (circleWithRingBitmap != null) {
					drawable = new BitmapDrawable(circleWithRingBitmap);
				}
				imageCache.put(imageUrl, new SoftReference<Drawable>(drawable));
				System.gc();
				Message message = handler.obtainMessage(0, drawable);
				handler.sendMessage(message);
				
			}
		}.start();
		return null;
	}

	
	/**
	 * 
	 * load image by url , and cache it
	 * 
	 * */
	/*public static Bitmap loadImageFromUrl(String url, boolean compress) {
		
		if (url == null) {
			return null;
		}
		Bitmap bitmap = null;
		
		URL m;
		InputStream is = null;
		//Drawable d = null;
		
		try {
			m = new URL(url);
			is = (InputStream) m.getContent();
			BitmapDrawable bd = (BitmapDrawable)Drawable.createFromStream(is, "src");
			
			if (bd != null) {
				if (compress) {
					bitmap = compressBitmap(bd.getBitmap());
				}
				else {
					bitmap = bd.getBitmap();
				}
			}
			//}
			
			bd = null;
			
			System.gc();
			
		} catch (MalformedURLException e1) {
			e1.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (is != null) {
					is.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		if (bitmap != null) {
			
			String type = "";
			
			String[] strings = url.split("\\.");
			
			if (strings != null && strings.length > 0) {
				type = strings[strings.length - 1];
			}
			
			File cacheFile = new File(Constant.AppDir.DIR_CACHE_IMAGE + File.separator + StringUtil.convertUrlToSecretFileName(url));
			
			CacheUtil.saveBitmapToCache(bitmap, type, cacheFile);
			
		}
		
		return bitmap;
		
	}*/
	
	
	public static Bitmap loadImageFromUrl(String url, boolean compress,int width,int height) {
	   TTLog.s("imageUrl------------"+url);
		if (url == null) {
			return null;
		}
		
		Bitmap bitmap = null;
		
		URL m;
		InputStream is = null;
		//Drawable d = null;
		
		try {
			m = new URL(url);
			is = (InputStream) m.getContent();
			
			BitmapFactory.Options opts = new BitmapFactory.Options();
			
			if (compress) {
				switch(Constant.mScreenType) {
				case Constant.ScreenSplashType.DEVICE_ANDROID_LDPI:
					opts.inSampleSize = Constant.ImageSampleSize.SAMPLE_SIZE_LDPI;
					break;
					
				case Constant.ScreenSplashType.DEVICE_ANDROID_MDPI:
					opts.inSampleSize = Constant.ImageSampleSize.SAMPLE_SIZE_MDPI;
					break;
					
				case Constant.ScreenSplashType.DEVICE_ANDROID_HDPI:
					opts.inSampleSize = Constant.ImageSampleSize.SAMPLE_SIZE_HDPI;
					break;
			
				case Constant.ScreenSplashType.DEVICE_ANDROID_XDPI:
					opts.inSampleSize = Constant.ImageSampleSize.SAMPLE_SIZE_XDPI;
					break;
					
				}
				
			}
			else {
				opts.inSampleSize = 1;
			}
			TTLog.s(width+"----loadImageFromUrl-122----"+height);
//			if(width==0&&height==0){
			
				bitmap = BitmapFactory.decodeStream(new BufferedInputStream(is, 16*1024), null, opts);	
//			}
//			else{
//				opts.outHeight=height;
//				opts.outWidth=width;
//				bitmap=BitmapFactory.decodeStream( new BufferedInputStream(is, 16*1024),null,opts);
//			}
//			TTLog.s(bitmap.getPicWidth()+"----loadImageFromUrl-----"+bitmap.getHeight());
		} catch (MalformedURLException e1) {
			e1.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}catch (OutOfMemoryError e){
			e.printStackTrace();
		}
		finally {
			try {
				if (is != null) {
					is.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		if (bitmap != null) {
			
			String type = "";
			
			String[] strings = url.split("\\.");
			
			if (strings != null && strings.length > 0) {
				type = strings[strings.length - 1];
			}
			
			File cacheFile = new File(Constant.AppDir.DIR_CACHE_IMAGE + File.separator + StringUtil.convertUrlToSecretFileName(url));
			
			CacheUtil.saveBitmapToCache(bitmap, type, cacheFile);
			
		}
		
		return bitmap;
		
	}
	
	private static Bitmap compressBitmap(Bitmap bitmap) {  
	      
	    ByteArrayOutputStream baos = new ByteArrayOutputStream();         
	    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);  
	    if( baos.toByteArray().length / 1024 > 1024) {
	        baos.reset();
	        bitmap.compress(Bitmap.CompressFormat.JPEG, 50, baos);
	    }  
	    
	    if (bitmap != null && !bitmap.isRecycled()) {
	    	bitmap.recycle();
	    	bitmap = null;
	    }
	    
	    System.gc();
	    
	    ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());  
	    BitmapFactory.Options newOpts = new BitmapFactory.Options();  
	    newOpts.inJustDecodeBounds = true;  
	    Bitmap bitmap2 = BitmapFactory.decodeStream(isBm, null, newOpts);  
	    newOpts.inJustDecodeBounds = false;  
	    int width = newOpts.outWidth;  
	    int height = newOpts.outHeight;  
	    float maxHeight = Constant.mMaxThumbnailHeight; 
	    float maxWdith = Constant.mMaxThumbnailWidth; 
	    int scale = 1;
	    if (width > height && width > maxWdith) {
	    	scale = (int) (newOpts.outWidth / maxWdith);  
	    } else if (width < height && height > maxHeight) {
	    	scale = (int) (newOpts.outHeight / maxHeight);  
	    }  
	    if (scale <= 0)  
	    	scale = 1;  
	    newOpts.inSampleSize = scale;
	    isBm = new ByteArrayInputStream(baos.toByteArray());  
	    bitmap2 = BitmapFactory.decodeStream(isBm, null, newOpts);  
	    return bitmap2;
	}  
	
	/*public static Bitmap loadImageFromUrl(String url) {
		
		File cacheFile = new File(Constant.AppDir.DIR_CACHE_IMAGE + File.separator + StringUtil.convertUrlToSecretFileName(url));
		
		return loadImageFromUrl(null, cacheFile);
	}*/
	
	
	public static Bitmap convert2CirlcleBitmap(Bitmap bitmap) {
		
		if (bitmap == null) {
			return null;
		}
		
		return BitmapUtil.getCircleBitmap(bitmap);
	}
	
	/**
	 * you can control the ring width, because that any image is not the same size
	 * */
	@Deprecated
	public static Bitmap convert2CirlcleWithRingBitmap(Bitmap bitmap, int ringWidth) {
		
		if (bitmap == null) {
			return null;
		}
		
		return BitmapUtil.getCircleBitmapWithRing(bitmap, ringWidth);
	}
	
	
	/**
	 * 
	 * load avatar image will not add suffix
	 * */
	public static void loadAvatarFromUrl(String url) {
		
		if (url == null) {
			return;
		}
		
		
		Bitmap bitmap = null;
		
		
		// if cache exist , so just get image from local cache
		// but here may be slow , so we don't want it here
		/*if (cacheFile.exists()) {
			TTLog.e("loadImageFromUrl", "cache image exist , read from cache!");
			return new BitmapDrawable(CacheUtil.readBitmapFromCache(type, cacheFile));
		}*/
		
		URL m;
		InputStream is = null;
		//Drawable d = null;
		
		try {
			m = new URL(url);
			is = (InputStream) m.getContent();
			//d = Drawable.createFromStream(i, "src");
			
			Options opts = new BitmapFactory.Options(); 
	        
	        //first , will not return bitmap object, require none memory
			opts.inJustDecodeBounds = true; 
	        //bitmapFactoryOptions.inSampleSize = 2;
	        bitmap = BitmapFactory.decodeStream(is, null, opts);
	        float imagew = Constant.mMaxThumbnailHeight; 
	        float imageh = Constant.mMaxThumbnailWidth; 
	        int yRatio = (int) Math.floor(opts.outHeight / imageh); 
	        int xRatio = (int) Math.floor(opts.outWidth / imagew); 
	        TTLog.e("BMw&h1", opts.outWidth + ":" + opts.outHeight);
	        if (yRatio > 1 || xRatio > 1) { 
	            if (yRatio > xRatio) { 
	            	opts.inSampleSize = yRatio; 
	            } else { 
	            	opts.inSampleSize = xRatio; 
	            } 

	        }  
	        
	        // reset
	        opts.inJustDecodeBounds = false; 
	        
	        if (is != null) {
	        	is.close();
	        }
	        
	        is = (InputStream) m.getContent();
			bitmap = BitmapFactory.decodeStream(is, null, opts);
			
		} catch (MalformedURLException e1) {
			e1.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (is != null) {
					is.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		if (bitmap != null) {
			
			String type = "";
			
			String[] strings = url.split("\\.");
			
			if (strings != null && strings.length > 0) {
				type = strings[strings.length - 1];
			}
			
			File cacheFile = new File(Constant.AppDir.DIR_CACHE_IMAGE + File.separator + StringUtil.convertUrlToFileName(url));
			
			CacheUtil.saveBitmapToCache(bitmap, type, cacheFile);
			
			//bitmap = BitmapUtil.toRoundBitmap(bitmap);
			TTLog.e("BMw&h2", bitmap.getWidth() + ":" + bitmap.getHeight());
		}
		
		/*if (bitmap != null && bitmap.isRecycled()) {
			bitmap.recycle();
			System.gc();
		}
		
		
		
		return new BitmapDrawable();*/
	}
	
	/**
	 * 
	 * load screen splash from url 
	 * 
	 * */
	public static Bitmap loadScreenSplashFromUrl(String url) {
		
		if (url == null) {
			return null;
		}
		Bitmap bitmap = getBitmap(url);
		
//		URL m;
//		InputStream is = null;
//		//Drawable d = null;
//
//		try {
//			m = new URL(url);
//			is = (InputStream) m.getContent();
//
//			BitmapDrawable bd = (BitmapDrawable)Drawable.createFromStream(is, "src");
//
//			if (bd != null) {
//				bitmap = bd.getBitmap();
//			}
//		} catch (MalformedURLException e1) {
//			e1.printStackTrace();
//		} catch (IOException e) {
//			e.printStackTrace();
//		} finally {
//			try {
//				if (is != null) {
//					is.close();
//				}
//			} catch (IOException e) {
//				e.printStackTrace();
//			}
//		}

		
		if (bitmap != null) {
			
			String type = "";
			
			String[] strings = url.split("\\.");
			
			if (strings != null && strings.length > 0) {
				type = strings[strings.length - 1];
			}
			FileUtil2.deleteAllWithPath(Constant.AppDir.DIR_CACHE_SPLASH);
			File cacheFile = new File(Constant.AppDir.DIR_CACHE_SPLASH + StringUtil.convertUrlToFileName(url));
			
			CacheUtil.saveBitmapToCache(bitmap, type, cacheFile);
			
			if (bitmap.isRecycled()) {
				bitmap.recycle();
				System.gc();
			}
		}
		
		return bitmap;
		
	}


	/**
	 * 将网络资源图片转换为Bitmap
	 * @param imgUrl 网络资源图片路径
	 * @return Bitmap
	 * 该方法调用时要放在子线程中
	 */
	public static Bitmap netToLoacalBitmap(String imgUrl){
		Bitmap bitmap = null;
		InputStream in=null;
		BufferedOutputStream out = null;
		try{
			in = new BufferedInputStream(new URL(imgUrl).openStream(),1024);
			final ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
			out = new BufferedOutputStream(dataStream,1024);
			copy(in,out);
			out.flush();
			byte[] data = dataStream.toByteArray();
			bitmap = BitmapFactory.decodeByteArray(data,0,data.length);
			data = null;
			return bitmap;
		}catch (IOException e){
			e.printStackTrace();
			return null;
		}
	}

	private static void copy(InputStream in, OutputStream out)
			throws IOException {
		byte[] b = new byte[1024];
		int read;
		while ((read = in.read(b)) != -1) {
			out.write(b, 0, read);
		}
	}


	public static Bitmap getBitmap(String url) {
		Bitmap bm = null;
		try {
			URL iconUrl = new URL(url);
			URLConnection conn = iconUrl.openConnection();
			HttpURLConnection http = (HttpURLConnection) conn;

			int length = http.getContentLength();

			conn.connect();
			// 获得图像的字符流
			InputStream is = conn.getInputStream();
			BufferedInputStream bis = new BufferedInputStream(is, length);
			bm = BitmapFactory.decodeStream(bis);
			bis.close();
			is.close();// 关闭流
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		return bm;
	}


	private void queuePhoto(String url, ImageView imageView,ImageCallback download,boolean compress,int width,int height) {
	        PhotoToLoad p = new PhotoToLoad(url, imageView);  
//	        executorService.submit(new PhotosLoader(p, url, download,  compress, width,  height));  
	 }
    class PhotosLoader implements Runnable {  
        PhotoToLoad photoToLoad;  
		private String url;
		private ImageCallback download;
		private boolean compress;
		private int width=0;
		private int height=0;
		public PhotosLoader(PhotoToLoad photoToLoad,String url,ImageCallback download,boolean compress,int width,int height){
			this.url = url;
			this.download = download;
			this.compress=compress;
			this.width=width;
			this.height=height;
			this.photoToLoad=photoToLoad;
		}
		private Handler imagHandler=new Handler(){
			@Override
			public void handleMessage(Message message) {
				download.imageLoaded((Drawable) message.obj, url);
			}
	     };
        @Override  
        public void run() {  
        	TTLog.s("---"+imageViewReused(photoToLoad));
            if (imageViewReused(photoToLoad))  
                return;  
             Drawable drawable = null;
			
			Bitmap normalBitmap = loadImageFromUrl(photoToLoad.url, compress,width,height);
			
			if (normalBitmap != null) {
				drawable = new BitmapDrawable(normalBitmap);
			}
			imageCache.put(url, new SoftReference<Drawable>(drawable));
			System.gc();
        	
			Message message = imagHandler.obtainMessage(0, drawable);
			imagHandler.sendMessage(message);
        }  
        }
      
    /** 
     * 防止图片错位 
     *  
     * @param photoToLoad 
     * @return 
     */  
    boolean imageViewReused(PhotoToLoad photoToLoad) {  
        String tag = imageViews.get(photoToLoad.imageView);  
        TTLog.s(tag+"****"+photoToLoad.url);
        if (tag == null || !tag.equals(photoToLoad.url))  
            return true;  
        return false;  
    }  
    // Task for the queue  
    private class PhotoToLoad {  
        public String url;  
        public ImageView imageView;  
  
        public PhotoToLoad(String u, ImageView i) {  
            url = u;  
            imageView = i;  
        }  
    }  
	/**
	 * 判断是否需要重新创建线程下载图片，如果需要，返回值为true。
	 * @param mImageView
	 * @return
	 */
	private boolean needCreateNewTask(ImageView mImageView){
		boolean b = true;
		if(mImageView != null){
			String curr_task_url = (String)mImageView.getTag();
			if(isTasksContains(curr_task_url)){
				b = false;
			}
		}
		return b;
	}
	
	/**
	 * 检查该url（最终反映的是当前的ImageView的tag，tag会根据position的不同而不同）对应的task是否存在
	 * @param url
	 * @return
	 */
	private boolean isTasksContains(String url){
		boolean b = false;
		if(map != null && map.get(url) != null){
			b = true;
		}
		return b;
	}
	/**
	 * 删除map中该url的信息，这一步很重要，不然MyAsyncTask的引用会“一直”存在于map中
	 * @param url
	 */
	private void removeTaskFormMap(String url){
		if(url != null && map != null && map.get(url) != null){
			map.remove(url);
			TTLog.s("当前map的大小=="+map.size());
		}
	}
	/**
	 * 异步下载图片的方法
	 * @author yanbin
	 *
	 */
	private class MyAsyncTask extends AsyncTask<String, Void, Drawable>{
		private ImageView mImageView;
		private String url;
		private ImageCallback download;
		private boolean compress;
		private int width=0;
		private int height=0;
		public MyAsyncTask(String url,ImageView mImageView,ImageCallback download,boolean compress,int width,int height){
			this.mImageView = mImageView;
			this.url = url;
			this.download = download;
			this.compress=compress;
			this.width=width;
			this.height=height;
		}

		@Override
		protected Drawable doInBackground(String... params) {
			Drawable drawable = null;
			
			Bitmap normalBitmap = loadImageFromUrl(url, compress,width,height);
			
			if (normalBitmap != null) {
				drawable = new BitmapDrawable(normalBitmap);
			}
			imageCache.put(url, new SoftReference<Drawable>(drawable));
			return  drawable;
		}

		@Override
		protected void onPreExecute() {
			super.onPreExecute();
		}

		@Override
		protected void onPostExecute(Drawable result) {
			//回调设置图片
			if(download != null){
				download.imageLoaded(result,url);
			}
			removeTaskFormMap(url);
			//该url对应的task已经下载完成，从map中将其删除
			System.gc();
			super.onPostExecute(result);
		}
		
	}

	public   interface  ImageCallback {
		   void imageLoaded(Drawable imageDrawable, String imageUrl);
	}
}
